package com.wx.forum.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.wx.forum.common.AppResult;
import com.wx.forum.common.ResultCode;
import com.wx.forum.contant.Contants;
import com.wx.forum.model.CaptchaProperties;
import com.wx.forum.model.User;
import com.wx.forum.service.IAuthService;
import com.wx.forum.service.IUserService;
import com.wx.forum.utils.JwtUtil;
import com.wx.forum.utils.MD5Util;
import com.wx.forum.utils.StringUtil;
import com.wx.forum.utils.UUIDUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/user")
@Api(tags = "用户接口")
public class UserController {
    @Value("${forum.image.relativePath}")
    private String relativePath;//头像相对路径
    @Value("${forum.image.realPath}")
    private String realPath;
    @Resource
    private IUserService userService;
    @Autowired
    private CaptchaProperties captchaProperties;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private IAuthService authService;

    /**
     * 注册
     *
     * @param username
     * @param nickname
     * @param password
     * @param passwordRepeat
     * @return AppResult
     */
    @ApiOperation("注册用户API")
    @RequestMapping("/register")
    public AppResult regist(@ApiParam("用户名") @RequestParam("username") @NonNull String username,//对参数的描述，url中的key的名字，判空
                            @ApiParam("昵称") @RequestParam("nickname") @NonNull String nickname,
                            @ApiParam("密码") @RequestParam("password") @NonNull String password,
                            @ApiParam("重复密码") @RequestParam("passwordRepeat") @NonNull String passwordRepeat) {
        //判断重复密码是否相同
        if (!password.equals(passwordRepeat)) {
            log.warn(ResultCode.FAILED_TWO_PWD_NOT_S.toString());
            return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_S);
        }
        //准备数据
        User user = new User();
        user.setUsername(username);
        user.setNickname(nickname);

        //加密
        String salt = UUIDUtil.getUUID_32();//获得盐值
        password = MD5Util.md5Salt(password, salt);//生成密文

        user.setSalt(salt);
        user.setPassword(password);
        userService.createNormalUser(user);

        return AppResult.success("注册成功");
    }

    /**
     * 登录
     *
     * @param username
     * @param password
     * @return
     */
    @RequestMapping("/login")
    @ApiOperation("登录接口")
    public AppResult login(HttpSession session,
                           @ApiParam("登录用户名") @RequestParam("username") @NonNull String username,
                           @ApiParam("登录密码") @RequestParam("password") @NonNull String password,
                           @ApiParam("验证码") @RequestParam("code") @NonNull String code) {
        //1.校验验证码
        //获取uuid
        String verifyKey = (String) session.getAttribute(Contants.CAPTCHA_CODE_KEY);
        //从redis中拿
        String verifyCode = redisTemplate.opsForValue().get(verifyKey);
        //校验
        if(verifyCode == null || !code.equals(verifyCode)){
            //打印信息
            log.warn(ResultCode.FAILED_LOGIN.toString());
            return AppResult.failed("验证码不正确");
        }

        //2.调用service，获取用户信息
        User user = userService.login(username, password);
        if (user == null) {
            //打印信息
            log.warn(ResultCode.FAILED_LOGIN.toString() + "username: " + username);
            return AppResult.failed(ResultCode.FAILED_LOGIN);
        }
        //3.如果登录成功，返回token
        //获取token
        Map<String, Object> map = new HashMap<>();
        map.put(Contants.TOKEN_USER_USERANME, user.getUsername());
        map.put(Contants.TOKEN_USER_ID, user.getId());
        String token = JwtUtil.getToken(map);
        log.info("token {}", token);
        //4.将token存入redis
        authService.saveToken(user.getId(),token);

        return AppResult.success(token);
    }
    /**
     * 生成验证码
     * @param response
     * @param session
     * @throws IOException
     */
    @RequestMapping("/getCaptcha")
    public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {
        //生成验证码
        //CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(captchaProperties.getWidth(),captchaProperties.getHight(),4,180);
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(captchaProperties.getWidth(),captchaProperties.getHight());
        response.setContentType("image/jpeg");
        response.setHeader("Progma","No-cache");
        captcha.write(response.getOutputStream());
        //拿到生成的验证码
        String code = captcha.getCode();
        //存入redis
        String verifyKey = Contants.CAPTCHA_CODE_KEY + UUIDUtil.getUUID_32();
        redisTemplate.opsForValue().set(verifyKey,code,Contants.CAPTCHA_EXPIRATION, TimeUnit.SECONDS);
        //将验证码放到session中
        session.setAttribute(Contants.CAPTCHA_CODE_KEY,verifyKey);
        System.out.println("verifyKey: " + verifyKey);
        response.getOutputStream().close();
    }

    /**
     * 查询用户信息，如果id为空就使用token查询，如果不为空，就根据id查询
     *
     * @param id
     * @return
     */
    @ApiOperation("获取用户信息")
    @RequestMapping("/getUserInfo")
    public AppResult<User> getUserInfo(HttpServletRequest request,
                                       @ApiParam("用户id") @RequestParam(value = "id", required = false) Long id) {
        //required = false，表示可以为空
        User user = null;
        //1.如果id不为空，直接通过id查询用户信息
        if (id != null && id > 0) {
            user = userService.selectById(id);
            //2.如果id为空，通过token获取用户信息
        } else {
            //通过token获取id
            String token = request.getHeader(Contants.USER_TOKEN_HANDER);
            Long userId = JwtUtil.getIdByToken(token);
            log.info("token {} UerId {}", token, userId);
            if (userId == null || StringUtil.isEmpty(token)) {
                //用户未登录
                //打印信息
                log.warn(ResultCode.FAILED_FORBIDDEN.toString());
                return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
            }
            //通过id查找用户信息
            user = userService.selectById(userId);
        }
        //判空
        if (user == null) {
            //打印信息
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }

        return AppResult.success(user);

    }

    /**
     * 退出登录(待实现)
     * @return
     */
    @ApiOperation("退出登录")
    @RequestMapping("/logout")
    public AppResult logout(HttpServletRequest request){
        //通过token获取id
        String token = request.getHeader(Contants.USER_TOKEN_HANDER);
        Long userId = JwtUtil.getIdByToken(token);
        if (userId == null || StringUtil.isEmpty(token)) {
            //用户未登录
            //打印信息
            log.warn(ResultCode.FAILED_FORBIDDEN.toString());
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }
        //删除redis里的token
        authService.deleteToken(userId);
        log.info("用户UerId {}退出成功", userId);
        return AppResult.success();
    }

    /**
     * 修改用户信息
     * @param request
     * @param username 用户
     * @param nickname 昵称
     * @param gender 性别
     * @param email 邮箱
     * @param phoneNum 电话号码
     * @param remark 个人简介
     * @return
     */
    @ApiOperation("修改用户信息")
    @PostMapping("/modifyInfo")
    public AppResult<User> modifyInfo(HttpServletRequest request,
               @ApiParam("用户名") @RequestParam(value = "username", required = false) String username,
               @ApiParam("昵称") @RequestParam(value = "nickname", required = false) String nickname,
               @ApiParam("性别") @RequestParam(value = "gender", required = false) Byte gender,
               @ApiParam("邮箱") @RequestParam(value = "email", required = false) String email,
               @ApiParam("电话号码") @RequestParam(value = "phoneNum", required = false) String phoneNum,
               @ApiParam("个人简介") @RequestParam(value = "remark", required = false) String remark){
        //1.参数校验
        if(StringUtil.isEmpty(username) && StringUtil.isEmpty(nickname)
        && StringUtil.isEmpty(email) && StringUtil.isEmpty(phoneNum)
        && StringUtil.isEmpty(remark) && gender == null){
            //打印信息
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            return AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        //2.构建包装用户
        //通过token获取id
        String token = request.getHeader(Contants.USER_TOKEN_HANDER);
        Long userId = JwtUtil.getIdByToken(token);
        if (userId == null || StringUtil.isEmpty(token)) {
            //用户未登录
            //打印信息
            log.warn(ResultCode.FAILED_FORBIDDEN.toString());
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }
        User user = new User();
        user.setId(userId);
        user.setEmail(email);
        user.setGender(gender);
        user.setRemark(remark);
        user.setNickname(nickname);
        user.setUsername(username);
        user.setPhoneNum(phoneNum);
        //3.调用service
        userService.modifyInfo(user);
        //4.返回最新的用户信息
       // User newUser = userService.selectById(userId);
        return AppResult.success(user);
    }
    @ApiOperation("重置密码")
    @PostMapping("/modifyPwd")
    public AppResult modifyPassword(HttpServletRequest request,
                      @ApiParam("原始密码") @RequestParam("oldPassword") @NonNull String oldPassword,
                      @ApiParam("新密码") @RequestParam("newPassword") @NonNull String newPassword,
                      @ApiParam("重复密码") @RequestParam("passwordRepeat") @NonNull String passwordRepeat ){
        //通过token获取id
        String token = request.getHeader(Contants.USER_TOKEN_HANDER);
        Long userId = JwtUtil.getIdByToken(token);
        if (userId == null || StringUtil.isEmpty(token)) {
            //用户未登录
            //打印信息
            log.warn(ResultCode.FAILED_FORBIDDEN.toString());
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }

        //判断两次输入密码是否一致
        if(!newPassword.equals(passwordRepeat)){
            log.warn(ResultCode.FAILED_TWO_PWD_NOT_S.toString());
            return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_S);
        }

        //判断新密码不能和老密码一致
        if(oldPassword.equals(newPassword)){
            log.warn(ResultCode.FAILED_PASSWORD_EQUAL.toString());
            return AppResult.failed(ResultCode.FAILED_PASSWORD_EQUAL);
        }

        //调用service
        userService.modifyPassword(userId,oldPassword,newPassword);
        log.info("密码重置成功" + oldPassword + " -> " + newPassword + " UserId: " + userId);
        return AppResult.success();
    }
    @ApiOperation("更新头像")
    @PostMapping("/modifyAvatarUrl")
    public AppResult modifyAvatarUrl(HttpServletRequest request, MultipartFile file) throws IOException {
        //获取图片类型
        String imageType = file.getOriginalFilename().
                substring(file.getOriginalFilename().lastIndexOf("."));
        //文件名(随机生成字符串)
        String imgName = UUIDUtil.getUUID_32() + imageType;
        //创建图片文件
//        File dir = new File(relativePath);
//        String realPath = dir.getCanonicalPath();//获得绝对路径
//        try{
//            file.transferTo(new File(realPath+"/"+imgName));
//        } catch (Exception e){
//            return AppResult.failed(ResultCode.FAILED);
//        }
        file.transferTo(new File(realPath + imgName));
        //将图片地址保存到数据库,这个也是之后前端要请求的路径

        String imgUrl = "/image/" + imgName;
        //修改头像
        //通过token获取id
        String token = request.getHeader(Contants.USER_TOKEN_HANDER);
        Long userId = JwtUtil.getIdByToken(token);
        if (userId == null || StringUtil.isEmpty(token)) {
            //用户未登录
            //打印信息
            log.warn(ResultCode.FAILED_FORBIDDEN.toString());
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }
        System.out.println("imgUrl: " + imgUrl);
        int row = userService.updateAvatarUrl(userId,imgUrl);
        if(row != 1){
            return AppResult.failed(ResultCode.FAILED);
        }
        return AppResult.success(imgUrl);
    }
}
